﻿using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

namespace LightGameLibs.Editor
{
    public class LocalDBConfigWindow : EditorWindow
    {
        private string m_addEnumName = string.Empty;
        private DBTextAsset m_addEnumText = new DBTextAsset();
        private string m_addAssemblyName = string.Empty;
        private string m_addTypeName = string.Empty;
        private string m_enumScriptPath;
        private List<DBTag> m_tags = new List<DBTag>();
        private List<string> m_tagsString = new List<string>();
        private List<DBTextAsset> m_textAssets = new List<DBTextAsset>();
        private List<string> m_typeName = new List<string>();
        private List<string> m_assemblyName = new List<string>();
        private LocalDBConfig m_DBConfig;
        private Vector2 m_scrollPos;

        private const string c_scriptPathStoreKey = "LOCAL_DB_SCRIPTS_PATH";
        private bool m_check;

        [MenuItem("LightGameLibs/Configs/LocalDBConfig")]
        private static void ShowWindow()
        {
            GetWindow<LocalDBConfigWindow>(true, "LocalDBConfig").Show();
        }

        void Awake()
        {
            m_check = true;

            if (string.IsNullOrEmpty(EditorPrefs.GetString(c_scriptPathStoreKey, string.Empty)))
            {
                m_enumScriptPath = Application.dataPath.Add("/Plugins/LightGameLibs/LocalDatabase/GeneratedScripts/DBTag.cs");
                EditorPrefs.SetString(c_scriptPathStoreKey, m_enumScriptPath);
            }

            m_enumScriptPath = EditorPrefs.GetString(c_scriptPathStoreKey, m_enumScriptPath);

            if (!System.IO.File.Exists(m_enumScriptPath))
            {
                DebugMgr.LogError(DebugTag.LOCALDATABASE, "Cant find script");
                m_check = false;
            }

            m_DBConfig = (LocalDBConfig)Resources.Load(LocalDatabase.c_defaultPath, typeof(LocalDBConfig));
            if (null == m_DBConfig)
            {
                DebugMgr.LogError(DebugTag.LOCALDATABASE, "Cant find config in ".Add(LocalDatabase.c_defaultPath));
                m_check = false;
                return;
            }

            ReadConfigDict();
        }

        void OnGUI()
        {
            EditorGUILayout.BeginVertical();
            EditorGUILayout.LabelField("File Address:");
            if (EditorUtil.BrowsableAddress("Script", m_enumScriptPath, c_scriptPathStoreKey, "cs"))
            {
                m_check = true;
                m_enumScriptPath = EditorPrefs.GetString(c_scriptPathStoreKey);
            }
            EditorGUILayout.EndVertical();

            EditorGUILayout.BeginVertical();
            EditorGUILayout.LabelField("Config Path:    ".Add(Application.dataPath).Add("/").Add(LocalDatabase.c_defaultPath).Add(".asset"));
            EditorGUILayout.EndVertical();

            if (!m_check)
            {
                return;
            }

            EditorGUILayout.Space();
            EditorGUILayout.LabelField("Content:");

            EditorGUILayout.BeginVertical();
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Tag Name");
            EditorGUILayout.LabelField("Text");
            EditorGUILayout.LabelField("IsPreInit");
            EditorGUILayout.LabelField("AssemblyName");
            EditorGUILayout.LabelField("FullTypeName");
            EditorGUILayout.EndHorizontal();

            m_scrollPos = EditorGUILayout.BeginScrollView(m_scrollPos);
            for (int i = 0, length = m_tags.Count; i < length; i++)
            {
                EditorGUILayout.BeginHorizontal();
                m_tagsString[i] = EditorGUILayout.TextField(m_tagsString[i]);
                m_textAssets[i].m_text = (TextAsset)EditorGUILayout.ObjectField(m_textAssets[i].m_text, typeof(TextAsset), false);
                m_textAssets[i].m_isPreInit = EditorGUILayout.Toggle(m_textAssets[i].m_isPreInit);
                m_assemblyName[i] = EditorGUILayout.TextField(m_assemblyName[i]);
                m_typeName[i] = EditorGUILayout.TextField(m_typeName[i]);
                if (GUILayout.Button("Delete"))
                {
                    DeleteEnum(i);
                    return;
                }
                EditorGUILayout.EndHorizontal();
            }
            EditorGUILayout.EndScrollView();

            EditorGUILayout.BeginHorizontal();
            if (GUILayout.Button("Apply Setting"))
            {
                ConfigApply();
            }
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.EndVertical();

            EditorGUILayout.Space();
            EditorGUILayout.LabelField("Add:");

            EditorGUILayout.BeginVertical();
            EditorGUILayout.BeginHorizontal();
            m_addEnumName = EditorGUILayout.TextField("Enum Tag Name:", m_addEnumName).ToUpper();
            m_addEnumText.m_text = (TextAsset)EditorGUILayout.ObjectField(m_addEnumText.m_text, typeof(TextAsset), false);
            m_addEnumText.m_isPreInit = EditorGUILayout.Toggle(m_addEnumText.m_isPreInit);
            m_addAssemblyName = EditorGUILayout.TextField(m_addAssemblyName);
            m_addTypeName = EditorGUILayout.TextField(m_addTypeName);
            EditorGUILayout.EndHorizontal();
            if (GUILayout.Button("Add"))
            {
                AddEnum();
            }
            EditorGUILayout.EndVertical();
        }

        private void ConfigApply()
        {
            for (int i = 0, length = m_tags.Count; i < length; i++)
            {
                m_textAssets[i].m_assemblyName = m_assemblyName[i];
                m_textAssets[i].m_typeName = m_typeName[i];
                m_DBConfig.Tag2TextDict[m_tags[i]] = m_textAssets[i];
            }

            EditorUtil.WriteEnumToCS("DBTag", m_tagsString.ToArray(), "USER", (int)DebugTag.USER, m_enumScriptPath, string.Empty, "LightGameLibs");
            EditorUtility.SetDirty(m_DBConfig);
        }

        private void ReadConfigDict()
        {
            m_tags.Clear();
            m_tagsString.Clear();
            m_textAssets.Clear();
            m_typeName.Clear();
            m_assemblyName.Clear();
            foreach (var item in m_DBConfig.Tag2TextDict)
            {
                m_tags.Add(item.Key);
                m_tagsString.Add(item.Key.ToString());
                m_textAssets.Add(item.Value);
                m_typeName.Add(item.Value.m_typeName);
                m_assemblyName.Add(item.Value.m_assemblyName);
            }
        }

        private void AddEnum()
        {
            if (m_tagsString.Contains(m_addEnumName))
            {
                DebugMgr.Log(DebugTag.LOCALDATABASE, "Enum already exist");
                return;
            }

            if (string.IsNullOrEmpty(m_addEnumName))
            {
                DebugMgr.Log(DebugTag.LOCALDATABASE, "Please enter name");
                return;
            }

            m_addEnumText.m_assemblyName = m_addAssemblyName;
            m_addEnumText.m_typeName = m_addTypeName;

            int enumNum = EditorUtil.WriteEnumToCS("DBTag", m_tagsString.ToArray(), "USER", (int)DebugTag.USER, m_enumScriptPath, m_addEnumName, "LightGameLibs");

            m_DBConfig.Tag2TextDict.Add((DBTag)enumNum, m_addEnumText);
            m_tags.Add((DBTag)enumNum);
            m_tagsString.Add(m_addEnumName);
            m_textAssets.Add(m_addEnumText);

            EditorUtility.SetDirty(m_DBConfig);
        }

        private void DeleteEnum(int target)
        {
            m_DBConfig.Tag2TextDict.Remove(m_tags[target]);
            m_tags.RemoveAt(target);
            m_tagsString.RemoveAt(target);
            m_textAssets.RemoveAt(target);
            EditorUtil.WriteEnumToCS("DBTag", m_tagsString.ToArray(), "USER", (int)DebugTag.USER, m_enumScriptPath, string.Empty, "LightGameLibs");

            EditorUtility.SetDirty(m_DBConfig);
        }
    }
}
